-- CIS 552, Mini-project
-- by Mike Gottlieb and Reilly Grant

-- |Utility functions we wish were in the Prelude, but aren't.
module Util where

import List

-- |Count the number of elements in a list satisfying a predicate.
countWith :: (a -> Bool) -> [a] -> Int
countWith f as = sum $ map (\x -> if f x then 1 else 0) as

-- |Check that the list contains elements where one is the successor of the 
--  last.
increasingByOne :: (Enum a, Eq a) => [a] -> Bool
increasingByOne (a:as) = helper a as
    where helper a [] = True
          helper a (a':as) = if a' == (succ a) 
                               then helper a' as
                               else False

-- |Count the number of duplicate entries in a list and return a list of tuples
--  (element, # of duplicates).
countDups :: (Eq a) => [a] -> [(a, Int)]
countDups as = let uniq = nub as 
                   countEq x = countWith (x==) as
               in map (\x -> (x, countEq x)) uniq

-- |Attempt to parse a String, returning Nothing if the parse fails.
readMaybe :: (Read a) => String -> Maybe a
readMaybe s = let read = reads s in
              case read of
                [] -> Nothing
                rs -> Just $ fst $ head rs

-- |Replace the nth element of a list with the given element.
replace :: Int -> a -> [a] -> [a]
replace _ _ [] = error "Cannot replace element of an empty list."
replace 0 x (a:as) = x : as
replace n x (a:as) = a : replace (n-1) x as

-- |Perform monadic action if Maybe has a value, otherwise return unit.
maybeM :: (Monad m) => (a -> m b) -> Maybe a -> m (Maybe b)
maybeM f a = maybe (return Nothing) (\x -> do { r <- f x; return $ Just r }) a
